package school.community.service;

import school.community.dto.NotificationDTO;
import school.community.dto.PaginationDTO;
import school.community.enums.NotificationStatusEnum;
import school.community.enums.NotificationTypeEnum;
import school.community.exception.CustomizeErrorCode;
import school.community.exception.CustomizeException;
import school.community.mapper.NotificationMapper;
import school.community.model.Comment;
import school.community.model.Notification;
import school.community.model.NotificationExample;
import school.community.model.User;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class NotificationService {

  @Autowired
  private NotificationMapper notificationMapper;

  public PaginationDTO list(Long userId, Integer page, Integer size) {

    PaginationDTO<NotificationDTO> paginationDTO = new PaginationDTO<>();

    Integer totalPage;

    NotificationExample notificationExample = new NotificationExample();
    notificationExample.createCriteria()
            .andReceiverEqualTo(userId);
    Integer totalCount = (int) notificationMapper.countByExample(notificationExample);

    if (totalCount % size == 0) {
      totalPage = totalCount / size;
    } else {
      totalPage = totalCount / size + 1;
    }

    if (page < 1) {
      page = 1;
    }
    if (page > totalPage) {
      page = totalPage;
    }

    paginationDTO.setPagination(totalPage, page);

    //size*(page-1)
    Integer offset = size * (page - 1);
    NotificationExample example = new NotificationExample();
    example.createCriteria()
            .andReceiverEqualTo(userId);
    example.setOrderByClause("gmt_create desc");

    List<Notification> notifications = notificationMapper.selectByExampleWithRowbounds(example, new RowBounds(offset, size));

    if (notifications.size() == 0) {
      return paginationDTO;
    }

    List<NotificationDTO> notificationDTOS = new ArrayList<>();

    for (Notification notification : notifications) {
      NotificationDTO notificationDTO = new NotificationDTO();
      BeanUtils.copyProperties(notification, notificationDTO);
      notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
      notificationDTOS.add(notificationDTO);
    }
    paginationDTO.setData(notificationDTOS);
    return paginationDTO;
  }

  public Long unreadCount(Long userId) {
    NotificationExample notificationExample = new NotificationExample();
    notificationExample.createCriteria()
            .andReceiverEqualTo(userId)
            .andStatusEqualTo(NotificationStatusEnum.UNREAD.getStatus());
    return notificationMapper.countByExample(notificationExample);
  }

  public NotificationDTO read(Long id, User user) {
    Notification notification = notificationMapper.selectByPrimaryKey(id);
    if (notification == null) {
      throw new CustomizeException(CustomizeErrorCode.NOTIFICATION_NOT_FOUND);
    }
    if (!Objects.equals(notification.getReceiver(), user.getId())) {
      throw new CustomizeException(CustomizeErrorCode.READ_NOTIFICATION_FAIL);
    }

    notification.setStatus(NotificationStatusEnum.READ.getStatus());
    notificationMapper.updateByPrimaryKey(notification);

    NotificationDTO notificationDTO = new NotificationDTO();
    BeanUtils.copyProperties(notification, notificationDTO);
    notificationDTO.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
    return notificationDTO;
  }

  public void createNotify(Comment comment, Long receiver, String notifierName, String outerTitle, NotificationTypeEnum notificationType, Long outerId) {
    if (receiver == comment.getCommentator()) {
      return;
    }
    Notification notification = new Notification();
    notification.setGmtCreate(System.currentTimeMillis());
    notification.setType(notificationType.getType());
    notification.setOuterid(outerId);
    notification.setNotifier(comment.getCommentator());
    notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
    notification.setReceiver(receiver);
    notification.setNotifierName(notifierName);
    notification.setOuterTitle(outerTitle);
    notificationMapper.insert(notification);
  }

  public void createNotify(Long notifier, Long receiver, String notifierName, Long infoId, String infoTitle, NotificationTypeEnum notificationType) {

    if (receiver.equals(notifier)) {
      return;
    }
    Notification notification = new Notification();
    notification.setGmtCreate(System.currentTimeMillis());
        /*
            通知的类型
            REPLY_TALK(1, "回复了说说"),
            REPLY_COMMENT(2, "回复了评论"),
            PUBLISH_ACTIVITY(3,"发布活动");
         */
    notification.setType(notificationType.getType());
    //对应info的id
    notification.setOuterid(infoId);
    //发起通知者
    notification.setNotifier(notifier);
    //通知的状态，未读
        /*
            通知的状态：
            UNREAD(0),
            READ(1);
         */
    notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
    notification.setReceiver(receiver);
    notification.setNotifierName(notifierName);
    //对应的info的标题
    notification.setOuterTitle(infoTitle);
    notificationMapper.insert(notification);
  }
}
